package org.biloxi.game.gamerules;

import java.util.List;

import org.biloxi.commands.Command;
import org.biloxi.commands.CommandRepository;
import org.biloxi.commands.Listener;
import org.biloxi.commands.endgame.EndGame;
import org.biloxi.commands.playerlost.PlayerLost;
import org.biloxi.commands.playerlost.PlayerLost.Options;
import org.biloxi.commands.playerlost.PlayerLost.Result;
import org.biloxi.model.GameState;
import org.biloxi.player.PlayerID;

/**
 * This GameRule is responsible for determining when the end of the game has been reached.
 * Specifically listens to a set of commands that could indicate the end of the game.
 * 
 * Currently listens to the following commands:
 * 		- {@link PlayerLost}
 * 
 * @author Peter.WM.Wong@gmail.com
 */
public class EndGameRule extends GameRule {
		
	/**
	 * Listens to the {@link PlayerLost} command and keeps track of all the players that have lost.
	 * When all or all but one of the players of lost calls the {@link EndGame} command.
	 *  
	 * @author Peter.WM.Wong@gmail.com
	 */
	private class PlayerLostListener implements Listener<PlayerLost.Options, PlayerLost.Result> {
		private final List<PlayerID> nonLosers;
		
		public PlayerLostListener(List<PlayerID> pids) {
			nonLosers = pids;
		}

		public void handle(Command<Options, Result> cmd, Options options, Result result, GameState g) {
			nonLosers.remove(result.losingPlayer);
			if(nonLosers.size()<=1)
				_c.endGame( new EndGame.Options(nonLosers) );	
		}
	}
	
	/**
	 * Attaches rule by registering listeners to {@link PlayerLost} commands.
	 * @param c
	 * @param nls
	 */
	public EndGameRule(CommandRepository c, List<PlayerID> nls) {
		super(c);

		// Attach Listeners
		c.playerLost().do_(new PlayerLostListener(nls));
	}

}
